﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.IO;
using ProjetoKinect.Model;
using System.Globalization;
using ProjetoKinect.enums;
using Leap;
using ProjetoKinect.View2d;
using ProjetoKinect.LeapMotionGestures;
using Microsoft.Kinect.Toolkit.Controls;

namespace ProjetoKinect
{
    /// <summary>
    /// Interaction logic for ImageManipulation.xaml
    /// </summary>
    public partial class View2D : Grid
    {
        private DrawingGroup drawingGroup;
        private DrawingImage imageSource;
        private BodyControl bodyControl = new BodyControl();
        private int imageZoom = 500;
        private int placeX = 0;
        // private int placeX = 1000;
        private int placeY = 0;
        private string imagePath;
        private const float RenderWidth = 640.0f;
        private const float RenderHeight = 480.0f;
        private Select2DWindow select2DWindow;
        private Boolean hasRemoved = false;
        private KinectController kinectController;
        private Controller lmController = LeapMotionController.getInstance();
        private LeapMotionListennerV2d lmListennerV2d = LeapMotionListennerV2d.getInstance();

        public View2D(String imagePath, Select2DWindow mainWindow)
        {
            InitializeComponent();
            this.imagePath = imagePath;
            this.select2DWindow = mainWindow;
            this.kinectController = new KinectController();

        }

        private void WindowLoaded(object sender, RoutedEventArgs e)
        {
            //get kinectSensor

            this.drawingGroup = new DrawingGroup();

            // Create an image source that we can use in our image control
            this.imageSource = new DrawingImage(this.drawingGroup);

            // Display the drawing using our image control
            image.Source = this.imageSource;

            kinectController.findKinectSensor();
            kinectController.enableSkeletonStream(this.SensorSkeletonFrameReady);
         //   lmController.AddListener(lmListennerV2d);
           

            lmListennerV2d = LeapMotionListennerV2d.getInstance();
            lmListennerV2d.setView2dConfig(new View2dConfig(0, 0, 500));
            lmListennerV2d.setView2D(this);
            lmController.AddListener(lmListennerV2d);
            leapMotionManipulation();

        }
        
        public void leapMotionManipulation()
        {
            Dispatcher.BeginInvoke(new System.Threading.ThreadStart(delegate
             {
                 using (DrawingContext dc = this.drawingGroup.Open())
                 {
                     if (lmListennerV2d.shouldExit)
                     {
                         lmListennerV2d.shouldExit = false;
                         exitWithSecurity();
                     }
                     else
                     {
                         placeX = lmListennerV2d.view2dConfig.getPlaceX();
                         placeY = lmListennerV2d.view2dConfig.getPlaceY();
                         imageZoom = lmListennerV2d.view2dConfig.getImageZoom();

                         dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, RenderWidth, RenderHeight));
                         BitmapImage bi = new BitmapImage(new Uri(@imagePath));
                         dc.DrawImage(bi, new Rect(placeX, placeY, imageZoom, imageZoom));

                         if (lmListennerV2d.view2dConfig.isTranslateEnabled())
                         {
                             this.selectedFunction.Text = "Translate";
                         }
                         else if (lmListennerV2d.view2dConfig.isZoomEnabled())
                         {
                             this.selectedFunction.Text = "Zoom";
                         }
                         this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, RenderWidth, RenderHeight));
                     }
                 }
             }));
        }


        private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            Skeleton[] skeletons = kinectController.getSkeletons(e);
            using (DrawingContext dc = this.drawingGroup.Open())
            {
                // Draw a transparent background to set the render size
                dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, RenderWidth, RenderHeight));
                if (skeletons.Length != 0)
                {
                    foreach (Skeleton skel in skeletons)
                    {
                        if (skel.TrackingState == SkeletonTrackingState.Tracked)
                        {
                            
                            this.controlImage(skel, dc);
                        }

                    }
                }

                this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, RenderWidth, RenderHeight));

            }
        }

        private void controlImage(Skeleton skeleton, DrawingContext drawingContext)
        {

            bodyControl.setSkeletonJoints(skeleton);

            MyJoint leftHandMyJoint = bodyControl.getMyJointByJointType(JointType.HandLeft);
            MyJoint rightHandMyJoint = bodyControl.getMyJointByJointType(JointType.HandRight);


            FormattedText leftY = getFormattedText("leftY = " + leftHandMyJoint.getLastY());
            //    drawingContext.DrawText(leftY, new Point(0, 50));
            FormattedText leftYstatus = getFormattedText("leftY = " + bodyControl.getLeftHandLocation());
            //   drawingContext.DrawText(leftYstatus, new Point(300, 50));

            FormattedText rightY = getFormattedText("rightY = " + rightHandMyJoint.getLastY());
            //  drawingContext.DrawText(rightY, new Point(0, 100));
            FormattedText rightYstatus = getFormattedText("rightY = " + bodyControl.getRightHandLocation());
            //   drawingContext.DrawText(rightYstatus, new Point(300, 100));

            FormattedText similar = getFormattedText("similar = " + areSimilarValues(leftHandMyJoint.getLastY(), rightHandMyJoint.getLastY()));
            //   drawingContext.DrawText(similar, new Point(0, 150));

            int zoomCounter = 25;

            //zoom 
            if (bodyControl.areTwoHandsUp())
            {
                this.selectedFunction.Text = "Zoom";
                if(bodyControl.areTwoHandsGetClose())
                {
                    imageZoom = imageZoom - zoomCounter;
                }
                else if (bodyControl.areTwoHandGetAway())
                {
                    imageZoom = imageZoom + zoomCounter;
                }
            }
            

            else if (bodyControl.getLeftHandLocation().Equals(HandLocation.LD))
            {
                int placeCounter = 15;
                if (zoomCounter > 0)
                {
                    //normalizing paceCounter 
                    placeCounter = placeCounter + (imageZoom / 100);
                }

                this.selectedFunction.Text = "Translate";
                if (bodyControl.isJoinDistantFromJointBase(JointType.HandRight, JointType.HipRight))
                {
                    if (bodyControl.getJointMovimentStatus(JointType.HandRight, Axis.AXIS_X).Equals(MovimentStatus.DECREASING))
                    {
                        placeX = placeX + placeCounter;
                    }
                    else if (bodyControl.getJointMovimentStatus(JointType.HandRight, Axis.AXIS_X).Equals(MovimentStatus.INCREASING))
                    {
                        placeX = placeX - placeCounter;
                    }

                    if (bodyControl.getJointMovimentStatus(JointType.HandRight, Axis.AXIS_Y).Equals(MovimentStatus.DECREASING))
                    {
                        placeY = placeY - placeCounter;
                    }
                    else if (bodyControl.getJointMovimentStatus(JointType.HandRight, Axis.AXIS_Y).Equals(MovimentStatus.INCREASING))
                    {
                        placeY = placeY + placeCounter;
                    }
                }
            }
            
            else {
                this.selectedFunction.Text = " ";
            }
            if (bodyControl.isSurrenderPose(null))
            {
                this.selectedFunction.Text = bodyControl.getPoseMessage();
                if (bodyControl.getSecCount() >= 1) {
                    
                    exit();
                }
            }
            else {
                bodyControl.setPose(Pose.NONE);
            }
           
            //  Image myImage = new Image();
            BitmapImage bi = new BitmapImage(new Uri(@imagePath));
            drawingContext.DrawImage(bi, new Rect(placeX, placeY, imageZoom, imageZoom));

        }
        public void exit()
        {
            if (!hasRemoved)
            {
                //this.kinectController.stopSensor();
                // new Select2DWindow().Show();
                select2DWindow.gridRegion.Children.Remove(this);
                select2DWindow.addKinectRegion();
                hasRemoved = true;
            }

        }
        public void exitWithSecurity()
        {

            Dispatcher.BeginInvoke(new System.Threading.ThreadStart(delegate
               {
                   exit();
               }));

        }
        private static bool areSimilarValues(float leftX, float rightX)
        {
            // se a diferença entre os numeros for <= 1 retorna true
            if (leftX < 0)
            {
                leftX = leftX * -1;
            } if (rightX < 0)
            {
                rightX = rightX * -1;
            }
            if (rightX >= leftX)
            {
                if (rightX - leftX <= 0.3)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            if (leftX >= rightX)
            {
                if (leftX - rightX <= 0.3)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }

        private static FormattedText getFormattedText(string stringX)
        {
            FormattedText formattedText = new FormattedText(
                stringX,
                CultureInfo.GetCultureInfo("en-us"),
                FlowDirection.LeftToRight,
                new Typeface("Verdana"),
                30,
                Brushes.Black);
            formattedText.MaxTextWidth = 600;
            formattedText.MaxTextHeight = 320;

            formattedText.SetForegroundBrush(
                                    new LinearGradientBrush(
                                    Colors.Orange,
                                    Colors.Teal,
                                    90.0),
                                    0, stringX.Length);

            return formattedText;

        }

        private void OnHandleHandMove(object source, HandPointerEventArgs args)
        {
            HandPointer ptr = args.HandPointer;
            if (ptr.HandEventType == HandEventType.Grip)
            {
                // TODO
            }
        }
    }
}
